package org.jie.guider.java.base.threadpool;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author LiJie
 */
public class ThreadPool {

    private ThreadPoolExecutor pool;

    public ThreadPool(String threadName, BlockingQueue<Runnable> queue) {
        pool = new ThreadPoolExecutor
            (2, 2, 30L, TimeUnit.SECONDS, queue,
             new MyThreadFactory(threadName), new MyRejectHandler());
    }

    private class MyThreadFactory implements ThreadFactory {

        private String threadName;

        public MyThreadFactory(String threadName) {
            this.threadName = threadName;
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r, threadName);
            thread.setDaemon(false);
            return thread;
        }
    }

    private class MyRejectHandler implements RejectedExecutionHandler {

        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            System.out.println("fail");
        }
    }

    private static class MyTask implements Runnable {

        private Object data;

        public MyTask(Object data) {
            this.data = data;
        }

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + Thread.currentThread().getId() + ": " + data);
            if (data instanceof Integer) {
                throw new RuntimeException(String.valueOf(data));
            }
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<Runnable> queue = new SynchronousQueue<>();
        ThreadPool pool = new ThreadPool("我的线程", queue);
        pool.pool.prestartAllCoreThreads();
        pool.pool.allowCoreThreadTimeOut(false);

        for (int x = 100; x < 110; ++x) {
            queue.put(new MyTask(x));
        }

        System.out.println("存活线程: " + pool.pool.getCorePoolSize());

        pool.pool.shutdown();

    }
}
